#pragma once

#ifdef __CYGWIN32__
	#define  WIN32_LEAN_AND_MEAN
	#include <windows.h>
#endif

#ifdef __APPLE__
	#include "OpenCL/cl.h"
#else
	#include "cl/cl.h"
#endif

#ifndef __CYGWIN32__
	#include <stdio.h>
	#include <stdlib.h>
	#include <string.h>
#else
	#include <cstdio>
	#include <cstdlib>
#endif
#define  LOGI(...) printf(__VA_ARGS__)
#define  LOGE(...) printf(__VA_ARGS__)


class CL_Test{
protected:
	// OpenCL Vars
	cl_context cxGPUContext;        // OpenCL context
	cl_command_queue cqCommandQueue;// OpenCL command que
	cl_platform_id cpPlatform;      // OpenCL platform
	cl_device_id cdDevice;          // OpenCL device
	cl_program cpProgram;           // OpenCL program
	cl_kernel ckKernel;             // OpenCL kernel
	cl_mem cmDevSrcA;               // OpenCL device source buffer A
	cl_mem cmDevSrcB;               // OpenCL device source buffer B
	cl_mem cmDevDst;                // OpenCL device destination buffer

	size_t szGlobalWorkSize;        // 1D var for Total # of work items
	size_t szLocalWorkSize;		    // 1D var for # of work items in the work group
	size_t szParmDataBytes;			// Byte size of context information
	size_t szKernelLength;			// Byte size of kernel code

	int iNumElements;				// Length of float arrays to process (odd # for illustration)

	cl_float *srcA, *srcB, *dst;        // Host buffers for OpenCL test

	void check_cl_error(cl_uint ret_code);
	// Round Up Division function
	size_t round_up(int group_size, int global_size);

	// Helper function to init data arrays
	void fill_array(float* pfData, int iSize);
public:
	CL_Test();
	void Cleanup();
};
